package org.jeecg.access.service.impl;

import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.access.constant.PlatformType;
import org.jeecg.access.entity.PlatformAccount;
import org.jeecg.access.mapper.PlatformAccountMapper;
import org.jeecg.access.platform.constant.DataState;
import org.jeecg.access.service.PlatformAccountService;
import org.jeecg.access.platform.service.PlatformHandler;
import org.jeecg.config.PlatformHandlerFactory;
import org.jeecg.util.DateTimeUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 平台账号服务实现类
 * 继承MyBatis-Plus的ServiceImpl，实现PlatformAccountService接口
 * 负责平台账号的CRUD操作及跨平台账号同步逻辑
 *
 * @author taogang
 * @date 2025/7/30 11:16
 */
@Slf4j
@Service
public class PlatformAccountServiceImpl extends ServiceImpl<PlatformAccountMapper, PlatformAccount> implements PlatformAccountService {

    /**
     * 平台处理器工厂
     * 用于根据平台类型获取对应的处理器实例，处理不同平台的账号同步与校验逻辑
     */
    @Autowired
    private PlatformHandlerFactory handlerFactory;

    /**
     * 保存平台账号信息
     * 新增账号时设置创建时间、更新时间和初始状态（正常）
     *
     * @param account 待保存的平台账号实体
     * @return 保存成功返回true，失败返回false
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveAccount(PlatformAccount account) {
        // 获取当前时间戳，用于创建时间和更新时间
        String currentTime = DateTimeUtil.getCurrentTimestamp();
        // 设置账号创建时间
        account.setCreateTime(currentTime);
        // 设置账号更新时间（新增时与创建时间一致）
        account.setUpdateTime(currentTime);
        // 设置账号初始状态：0表示正常（未删除）
        account.setState(DataState.INIT);
        // 调用父类方法保存账号信息
        return this.save(account);
    }

    /**
     * 更新平台账号信息
     * 仅当账号ID存在时执行更新，更新时刷新更新时间
     *
     * @param account 待更新的平台账号实体（需包含ID）
     * @return 更新成功返回true，失败返回false
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateAccount(PlatformAccount account) {
        // 校验账号ID是否存在，不存在则无法更新
        if (account.getId() == null) {
            log.warn("更新账号失败：账号ID不能为空");
            return false;
        }
        // 更新账号的最后修改时间
        account.setUpdateTime(DateTimeUtil.getCurrentTimestamp());
        // 调用Mapper更新账号信息，返回受影响行数是否大于0
        return baseMapper.updateById(account) > 0;
    }

    /**
     * 逻辑删除平台账号
     * 将账号状态设置为1（已删除），而非物理删除，保留数据记录
     *
     * @param id       待删除账号的ID
     * @param updater  操作人
     * @return 删除成功返回true，失败返回false
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteAccount(String id, String updater) {
        // 创建更新条件包装器
        UpdateWrapper<PlatformAccount> updateWrapper = new UpdateWrapper<>();
        // 条件：账号ID等于目标ID
        updateWrapper.eq("id", id);
        // 设置更新字段：状态改为1（已删除）
        updateWrapper.set("state", DataState.DELETE);
        // 设置更新人
        updateWrapper.set("updater", updater);
        // 设置更新时间
        updateWrapper.set("update_time", DateTimeUtil.getCurrentTimestamp());
        // 执行更新并返回结果
        return baseMapper.update(null, updateWrapper) > 0;
    }

    /**
     * 批量逻辑删除平台账号
     * 批量将账号状态设置为1（已删除），提高批量操作效率
     *
     * @param ids      待删除账号的ID列表
     * @param updater  操作人
     * @return 批量删除成功返回true，失败返回false
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean batchDeleteAccounts(List<String> ids, String updater) {
        // 获取当前时间戳作为更新时间
        String updateTime = DateTimeUtil.getCurrentTimestamp();
        // 创建更新条件包装器
        UpdateWrapper<PlatformAccount> updateWrapper = new UpdateWrapper<>();
        // 条件：账号ID在目标列表中
        updateWrapper.in("id", ids);
        // 设置更新字段：状态改为1（已删除）
        updateWrapper.set("state", DataState.DELETE);
        // 设置更新人
        updateWrapper.set("updater", updater);
        // 设置更新时间
        updateWrapper.set("update_time", updateTime);
        // 执行批量更新并返回结果
        return baseMapper.update(null, updateWrapper) > 0;
    }

    /**
     * 同步平台账号数据到对应平台的用户信息表，并校验账号可用性
     * 1. 按平台类型分组所有账号
     * 2. 对每个平台，处理未同步的账号：验证账号有效性，有效则同步，无效则标记异常
     * 3. 批量更新异常账号状态
     *
     * @return 异常账号列表（验证失败的账号）
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<PlatformAccount> syncPlatformAccounts(String platformType) {
        // 1. 查询所有平台账号（包含所有状态）
        List<PlatformAccount> allAccounts = this.list();
        log.info("开始同步平台账号，共查询到 {} 个账号", allAccounts.size());

        // 2. 按平台类型分组账号，便于按平台处理
        Map<String, List<PlatformAccount>> accountsByType = groupAccountsByType(allAccounts);

        // 3. 存储验证失败的异常账号
        List<PlatformAccount> abnormalAccounts = new ArrayList<>();

        // 4. 遍历每个平台的账号，进行同步和验证
        for (Map.Entry<String, List<PlatformAccount>> entry : accountsByType.entrySet()) {
            // 平台类型编码（如"REDBOOK"代表小红书）
            String platformTypeKey = entry.getKey();
            log.info(platformTypeKey +""+platformType);

            if((platformTypeKey != null && platformTypeKey.equals(platformType)) || null == platformTypeKey){
                // 获取该平台对应的处理器
                PlatformHandler handler = handlerFactory.getHandler(platformTypeKey);

                if (handler != null) {
                    // 处理该平台的账号同步与验证
                    processPlatformAccounts(entry.getValue(), handler, abnormalAccounts);
                } else {
                    log.warn("未找到平台[{}]对应的处理器，跳过该平台的账号同步", platformTypeKey);
                }
            }
        }

        // 5. 批量更新异常账号的状态（标记为5：验证失败）
        if (!abnormalAccounts.isEmpty()) {
            log.info("本次同步共发现 {} 个异常账号，开始更新状态", abnormalAccounts.size());
            this.updateBatchById(abnormalAccounts);
        } else {
            log.info("本次同步未发现异常账号");
        }

        // 返回异常账号列表
        return abnormalAccounts;
    }



    /**
     * 将账号列表按平台类型分组
     * 便于后续按平台类型分别处理不同平台的账号
     *
     * @param accounts 待分组的账号列表
     * @return 键为平台类型，值为该平台的账号列表的Map
     */
    private Map<String, List<PlatformAccount>> groupAccountsByType(List<PlatformAccount> accounts) {
        // 初始化分组Map
        Map<String, List<PlatformAccount>> result = new HashMap<>();

        // 遍历所有账号，按平台类型分组
        for (PlatformAccount account : accounts) {
            // 获取账号所属平台类型
            String type = account.getPlatformType();

            // 若Map中尚无该平台的列表，则初始化
            if (!result.containsKey(type)) {
                result.put(type, new ArrayList<>());
            }

            // 将账号添加到对应平台的列表中
            result.get(type).add(account);
        }

        return result;
    }

    /**
     * 处理特定平台的账号同步与验证
     * 1. 获取该平台已存在的用户数据（外部数据）
     * 2. 筛选出未同步到外部的账号
     * 3. 验证这些账号的有效性，有效则同步到外部，无效则标记为异常
     *
     * @param accounts         该平台的账号列表
     * @param handler          该平台的处理器
     * @param abnormalAccounts 存储异常账号的列表
     */
    private void processPlatformAccounts(List<PlatformAccount> accounts,
                                         PlatformHandler handler,
                                         List<PlatformAccount> abnormalAccounts) {
        // 1. 获取该平台已存在的用户数据（外部系统数据，如小红书的xhs_user_info表）
        List<?> externalData = handler.fetchExternalData();
        log.info("平台[{}]当前已存在 {} 条外部用户数据", handler.getPlatformType(), externalData.size());

        // 2. 筛选出未同步到外部系统的账号（即外部数据中不存在的账号）
        List<PlatformAccount> accountsToVerify = findAccountsNotInExternalData(accounts, externalData, handler);
        log.info("平台[{}]需验证的新账号数量：{}", handler.getPlatformType(), accountsToVerify.size());

        // 3. 逐个验证账号并处理
        for (PlatformAccount account : accountsToVerify) {
            log.debug("开始验证平台[{}]的账号：{}", handler.getPlatformType(), account.getAccountId());

            // 验证账号有效性（调用平台处理器的验证方法）
            if (handler.verifyAccount(account)) {
                // 验证通过：同步账号到外部系统（如写入xhs_user_info表）
                handler.writeToExternalSystem(account);
                log.debug("平台[{}]的账号[{}]验证通过并已同步", handler.getPlatformType(), account.getAccountId());
            } else {
                // 验证失败：标记账号状态为5（验证异常），记录更新人及时间
                account.setState(DataState.CHECK_FAIL);
                account.setUpdater("system");
                account.setUpdateTime(DateTimeUtil.getCurrentTimestamp());
                abnormalAccounts.add(account);
                log.warn("平台[{}]的账号[{}]验证失败，已标记为异常", handler.getPlatformType(), account.getAccountId());
            }
        }
    }

    /**
     * 筛选出未同步到外部系统的账号
     * 即：在平台账号列表中存在，但在外部系统数据中不存在的账号
     *
     * @param platformAccounts 平台账号列表
     * @param externalData     外部系统已存在的用户数据
     * @param handler          平台处理器（用于提取外部数据中的账号ID）
     * @return 未同步的账号列表
     */
    private List<PlatformAccount> findAccountsNotInExternalData(
            List<PlatformAccount> platformAccounts, List<?> externalData, PlatformHandler handler) {

        // 1. 提取外部系统中已存在的账号ID，存入Set便于快速查询
        Set<String> externalAccountIds = new HashSet<>();
        for (Object data : externalData) {
            // 通过处理器提取外部数据中的账号ID（如从XhsUserInfo中提取userId）
            String accountId = handler.extractAccountId(data);
            if (accountId != null) {
                externalAccountIds.add(accountId);
            }
        }
        log.debug("外部系统中已存在的账号ID数量：{}", externalAccountIds.size());

        // 2. 筛选出平台账号中不在外部系统中的账号
        List<PlatformAccount> result = new ArrayList<>();
        for (PlatformAccount account : platformAccounts) {
            // 若外部系统中不存在该账号ID，则需要验证和同步
            if (!externalAccountIds.contains(account.getId())) {
                result.add(account);
            }
        }
        return result;
    }
}
